package com.mofum.scope.annotation.controller.parser;

import com.mofum.scope.annotation.controller.ServiceColumn;
import com.mofum.scope.common.annotation.AnnotationParser;
import com.mofum.scope.common.annotation.metadata.controller.MServiceColumn;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yuyang@qxy37.com
 * @since 2019-03-27
 **/
public class ServiceColumnParser<T> implements AnnotationParser<Class<T>, MServiceColumn> {

    public Map<Field, MServiceColumn> parseField(Class<T> tClass) {

        Map<Field, MServiceColumn> map = new HashMap<Field, MServiceColumn>();

        Field[] fields = tClass.getDeclaredFields();

        for (Field field : fields) {

            if (field.isAnnotationPresent(ServiceColumn.class)) {

                ServiceColumn atColumn = field.getAnnotation(ServiceColumn.class);

                map.put(field, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Type, MServiceColumn> parseType(Class<T> tClass) {

        Map<Type, MServiceColumn> map = new HashMap<Type, MServiceColumn>();

        Class<?> clazz = tClass;

        if (clazz.isAnnotationPresent(ServiceColumn.class)) {

            ServiceColumn atColumn = clazz.getAnnotation(ServiceColumn.class);

            map.put(clazz, parse(atColumn));

        }

        return map;
    }

    public Map<Method, MServiceColumn> parseMethod(Class<T> tClass) {

        Map<Method, MServiceColumn> map = new HashMap<Method, MServiceColumn>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            if (method.isAnnotationPresent(ServiceColumn.class)) {

                ServiceColumn atColumn = method.getAnnotation(ServiceColumn.class);

                map.put(method, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Method, List<MServiceColumn>> parseParams(Class<T> tClass) {

        Map<Method, List<MServiceColumn>> map = new HashMap<Method, List<MServiceColumn>>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            List<MServiceColumn> list = new ArrayList<MServiceColumn>();

            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof ServiceColumn) {
                        ServiceColumn atColumn = (ServiceColumn) annotation;
                        list.add(parse(atColumn));
                    }
                }
            }

            map.put(method, list);
        }

        return map;
    }

    public MServiceColumn parse(ServiceColumn serviceColumn) {
        MServiceColumn mServiceColumn = new MServiceColumn();
        mServiceColumn.setMethod(serviceColumn.method());
        mServiceColumn.setName(serviceColumn.value());
        mServiceColumn.setType(serviceColumn.type());
        mServiceColumn.setArray(serviceColumn.array());
        mServiceColumn.setSplitRegex(serviceColumn.splitRegex());
        mServiceColumn.setJson(serviceColumn.json());
        return mServiceColumn;
    }

}
